package com.baiyi.homeui.hshomeui.util;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;

public class ByteTools {
    /**
     * 单精度浮点型转字节
     */
    public static byte[] float2ByteArray(float value) {
        return ByteBuffer.allocate(4).putFloat(value).array();
    }

    /**
     * 将字节数组前4字节转换为整型数值
     *
     * @param bytes
     * @return
     */
    public static int getInt(byte[] bytes) {
        return (0xff000000 & (bytes[0] << 24) | (0xff0000 & (bytes[1] << 16))
                | (0xff00 & (bytes[2] << 8)) | (0xff & bytes[3]));
    }

    /**
     * 将字节数组前4字节转换为整型数值
     *
     * @param bytes
     * @return
     */
    public static int getInt(byte[] bytes,int index) {
        return (0xff000000 & (bytes[0] << 24) | (0xff0000 & (bytes[1] << 16))
                | (0xff00 & (bytes[2] << 8)) | (0xff & bytes[3]));
    }




    /**
     * 将字节转整型
     *
     * @param b
     * @return
     */
    public static int byte2Int(byte b) {
        return (int)(b & 0xff);
    }

    /**
     * 将字节数组前2字节转换为short整型数值
     *
     * @param bytes
     * @return
     */
    public static short getShort(byte[] bytes) {
        return (short) ((0xff00 & (bytes[0] << 8)) | (0xff & bytes[1]));
    }

    /**
     * 将字节数组从startIndex开始的2个字节转换为short整型数值
     *
     * @param bytes
     * @param startIndex
     * @return
     */
    public static short getShort(byte[] bytes, int startIndex) {
        return (short) ((0xff00 & (bytes[startIndex] << 8)) | (0xff & bytes[startIndex + 1]));
    }

    /**
     * 将字节数组第0字节转换为布尔值
     *
     * @param bytes
     * @return
     */
    public static boolean getBoolean(byte[] bytes) {
        return bytes[0] == 1;
    }

    /**
     * 将字节数组的第index字节转换为布尔值
     *
     * @param bytes
     * @param index
     * @return
     */
    public static boolean getBoolean(byte[] bytes, int index) {
        return bytes[index] == 1;
    }

    /**
     * 将字节数组前4字节转换为float型数值
     *
     * @param bytes
     * @return
     */
    public static float getFloat(byte[] bytes) {
        return Float.intBitsToFloat(getInt(bytes));
    }

    /**
     * 将字节数组从startIndex开始的4个字节转换为float型数值
     *
     * @param bytes
     * @param startIndex
     * @return
     */
    public static float getFloat(byte[] bytes, int startIndex) {
        byte[] result = new byte[4];
        System.arraycopy(bytes, startIndex, result, 0, 4);
        return Float.intBitsToFloat(getInt(result));
    }

    /**
     * 将charsetName编码格式的字节数组转换为字符串
     *
     * @param bytes
     * @param charsetName
     * @return
     */
    public static String getString(byte[] bytes, String charsetName) {
        return new String(bytes, Charset.forName(charsetName));
    }

    //将整数数组转换成16字符串
    public static String byte2String(byte[] bytes) {
        StringBuilder builder = new StringBuilder();
        for (byte by : bytes) {
            int in;
            in = by & 0xFF;
            if (in > 15) {
                builder.append(Integer.toHexString(in));
            } else {
                builder.append("0").append(Integer.toHexString(in));
            }
        }
        System.out.println(builder.toString());
        return builder.toString();
    }
    /**
     * 将charsetName编码格式的字节数组转换为字符串
     *
     * @param bytes
     * @param startIndex
     * @param length
     * @param charsetName
     * @return
     */
    public static String getString(byte[] bytes, int startIndex, int length, String charsetName) {
        byte[] result = new byte[length];
        System.arraycopy(bytes, startIndex, result, 0, length);
        return new String(result, Charset.forName(charsetName));
    }

    /**
     * 字节数组拼接, srcArray拼接到desArray后面
     *
     * @param srcArray
     * @param desArray
     */
    public static byte[] byteArrayConcat(byte[] srcArray, byte[] desArray) {
        byte[] currentArray = new byte[srcArray.length + desArray.length];
        System.arraycopy(desArray, 0, currentArray, 0, desArray.length);
        System.arraycopy(srcArray, 0, currentArray, desArray.length, srcArray.length);
        return currentArray;
    }

    /**
     * 获取单个byte字节
     *
     * @param data
     * @return
     */
    public static byte[] getSingleByte(long data) {
        byte[] bytes = new byte[1];
        //-128~127
        if (-128l <= data && data <= 127l) {
            bytes[0] = (byte) data;
        } else {
            bytes[0] = (byte) -1;
        }
        return bytes;
    }

    /**
     * 获取short字节
     *
     * @param data
     * @return
     */
    public static byte[] getShortByte(long data) {
        short m = -1;
        //-32768~32767
        if (-32768l <= data && data <= 32767l) {
            m = (short) data;
        }
        byte[] bytes = getBytes(m);
        return bytes;
    }

    /**
     * 获取Int字节
     *
     * @param data
     * @return
     */
    public static byte[] getIntByte(long data) {
        int m = -1;
        //-2147483648~2147483647
        if (-2147483648l <= data && data <= 2147483647l) {
            m = (int) data;
        }
        byte[] bytes = getBytes(m);
        return bytes;
    }

    /**
     * 将short整型数值转换为字节数组
     *
     * @param data
     * @return
     */
    public static byte[] getBytes(short data) {
        byte[] bytes = new byte[2];
        bytes[0] = (byte) ((data & 0xff00) >> 8);
        bytes[1] = (byte) (data & 0xff);
        return bytes;
    }

    /**
     * 将整型数值转换为字节数组
     *
     * @param data
     * @return
     */
    public static byte[] getBytes(int data) {
        byte[] bytes = new byte[4];
        bytes[0] = (byte) ((data & 0xff000000) >> 24);
        bytes[1] = (byte) ((data & 0xff0000) >> 16);
        bytes[2] = (byte) ((data & 0xff00) >> 8);
        bytes[3] = (byte) (data & 0xff);
        return bytes;
    }

    /**
     * 将long整型数值转换为字节数组
     *
     * @param data
     * @return
     */
    public static byte[] getBytes(long data) {
        byte[] bytes = new byte[8];
        bytes[0] = (byte) ((data >> 56) & 0xff);
        bytes[1] = (byte) ((data >> 48) & 0xff);
        bytes[2] = (byte) ((data >> 40) & 0xff);
        bytes[3] = (byte) ((data >> 32) & 0xff);
        bytes[4] = (byte) ((data >> 24) & 0xff);
        bytes[5] = (byte) ((data >> 16) & 0xff);
        bytes[6] = (byte) ((data >> 8) & 0xff);
        bytes[7] = (byte) (data & 0xff);
        return bytes;
    }

    /**
     * 字节数组转16进制字符串
     * */
    public static String byteTo_16RadixString(byte[] buffer){
        String temString = "0x";
        for (byte b : buffer) {
            temString += Integer.toHexString(( b& 0x000000ff) | 0xffffff00).substring(6);
        }
        return temString;
    }

    /**
     * Byte转Bit
     */
    public static String byteToBit(byte b) {
        return "" +(byte)((b >> 7) & 0x1) +
                (byte)((b >> 6) & 0x1) +
                (byte)((b >> 5) & 0x1) +
                (byte)((b >> 4) & 0x1) +
                (byte)((b >> 3) & 0x1) +
                (byte)((b >> 2) & 0x1) +
                (byte)((b >> 1) & 0x1) +
                (byte)((b >> 0) & 0x1);
    }

    /**
     * Bit转Byte
     */
    public static byte bitToByte(String byteStr) {
        int re, len;
        if (null == byteStr) {
            return 0;
        }
        len = byteStr.length();
        if (len != 4 && len != 8) {
            return 0;
        }
        if (len == 8) {// 8 bit处理
            if (byteStr.charAt(0) == '0') {// 正数
                re = Integer.parseInt(byteStr, 2);
            } else {// 负数
                re = Integer.parseInt(byteStr, 2) - 256;
            }
        } else {//4 bit处理
            re = Integer.parseInt(byteStr, 2);
        }
        return (byte) re;
    }

    /**
     * byte[]转int
     *
     * @param bytes 一个byte数组
     * @param type  几个字节数想要转换int，从1开始
     * @return int
     */
    public static int bytes2Int(byte[] bytes, int type) {
        int num = 0;
        switch (type) {
            case 1:
                num = 0xFF & bytes[0];
                break;
            case 2:
                num = bytes[1] & 0xFF;
                num |= ((bytes[0] << 8) & 0xFF00);
                break;
            case 3:
                num = bytes[2] & 0xFF;
                num |= ((bytes[1] << 8) & 0xFF00);
                num |= ((bytes[0] << 16) & 0xFF0000);
                break;
            case 4:
                num = bytes[3] & 0xFF;
                num |= ((bytes[2] << 8) & 0xFF00);
                num |= ((bytes[1] << 16) & 0xFF0000);
                num |= ((bytes[0] << 24) & 0xFF0000);
                break;
        }

        return num;
    }

    public static int little_bytesToInt(byte[] bytes) {
        int addr = 0;
        if (bytes.length == 1) {
            addr = bytes[0] & 0xFF;
        } else if (bytes.length == 2) {
            addr = bytes[0] & 0xFF;
            addr |= (((int) bytes[1] << 8) & 0xFF00);
        } else if (bytes.length == 3) {
            addr = bytes[0] & 0xFF;
            addr |= ((bytes[1] << 8) & 0xFF00);
            addr |= ((bytes[2] << 16) & 0xFF0000);
        } else {
            addr = bytes[0] & 0xFF;
            addr |= (((int) bytes[1] << 8) & 0xFF00);
            addr |= (((int) bytes[2] << 16) & 0xFF0000);
            addr |= (((int) bytes[3] << 24) & 0xFF000000);
        }
        return addr;
    }

    public static int little_byteToInt(byte bytes) {
        int addr = 0;
        addr = bytes & 0xFF;
        return addr;
    }

    public static byte[] little_intToByte(int i, int len) {
        byte[] abyte = new byte[len];
        if (len == 1) {
            abyte[0] = (byte) (0xff & i);
        } else if (len == 2) {
            abyte[0] = (byte) (0xff & i);
            abyte[1] = (byte) ((0xff00 & i) >> 8);
        } else {
            abyte[0] = (byte) (0xff & i);
            abyte[1] = (byte) ((0xff00 & i) >> 8);
            abyte[2] = (byte) ((0xff0000 & i) >> 16);
            abyte[3] = (byte) ((0xff000000 & i) >> 24);
        }
        return abyte;
    }





    /**
     * int转byte[]
     *
     * @param i    一个int数字
     * @param type 想要转换得字节数，从1开始
     * @return byte[]
     */
    public static byte[] int2Bytes(int i, int type) {
        byte[] bytes = new byte[type];
        switch (type) {
            case 1:
                bytes[0] = (byte) (i & 0xFF);
                break;
            case 2:
                bytes[0] = (byte) ((i >> 8) & 0xFF);
                bytes[1] = (byte) (i & 0xFF);
                break;
            case 3:
                bytes[0] = (byte) ((i >> 16) & 0xFF);
                bytes[1] = (byte) ((i >> 8) & 0xFF);
                bytes[2] = (byte) (i & 0xFF);
                break;
            case 4:
                bytes[0] = (byte) ((i >> 24) & 0xFF);
                bytes[1] = (byte) ((i >> 16) & 0xFF);
                bytes[2] = (byte) ((i >> 8) & 0xFF);
                bytes[3] = (byte) (i & 0xFF);
                break;
        }

        return bytes;
    }


    public static String byteToHex(Byte inByte)
    {
        return String.format("%02x", inByte).toUpperCase();
    }

    public static String byteArrToHex(byte[] inBytArr)
    {
        StringBuilder strBuilder=new StringBuilder();
        int j=inBytArr.length;
        for (int i = 0; i < j; i++)
        {
            strBuilder.append(byteToHex(inBytArr[i]));
            //strBuilder.append(" ");
        }
        return strBuilder.toString();
    }

    public static String byteArrToHex(byte[] inBytArr,int offset,int byteCount)
    {
        StringBuilder strBuilder=new StringBuilder();
        int j=byteCount;
        for (int i = offset; i < j; i++)
        {
            strBuilder.append(byteToHex(inBytArr[i]));
        }
        return strBuilder.toString();
    }

    public static byte[] hexToByteArr(String inHex)
    {
        int hexlen = inHex.length();
        byte[] result;
        if (isOdd(hexlen)==1)
        {
            hexlen++;
            result = new byte[(hexlen/2)];
            inHex="0"+inHex;
        }else {
            result = new byte[(hexlen/2)];
        }
        int j=0;
        for (int i = 0; i < hexlen; i+=2)
        {
            result[j]=hexToByte(inHex.substring(i,i+2));
            j++;
        }
        return result;
    }

    /**
     * CRC校验
     * @param bytes
     * @param length
     * @return
     */
    public static  int CRC_cc(byte[] bytes, int length) {
//        LogUtil.logD(TAG, "len: "+length);
        short crc = 0;
        for (int i = 0; i < length; i++) {
            crc ^= (( short)bytes[i]) << 8;
            for (int n = 0; n < 8; n++) {
                if ((crc & 0x8000) == 0x8000) {
                    crc = (short) ((crc << 1) ^ 0x1021);
                } else {
                    crc = (short) (crc << 1);
                }
            }
        }
//        LogUtil.logD(TAG, "crc: "+crc);
        return getUnsignedShort(crc);
    }

    public static String getCRC(String data) {
        data = data.replace(" ", "");
        int len = data.length();
        if (!(len % 2 == 0)) {
            return "0000";
        }
        int num = len / 2;
        byte[] para = new byte[num];
        for (int i = 0; i < num; i++) {
            int value = Integer.valueOf(data.substring(i * 2, 2 * (i + 1)), 16);
            para[i] = (byte) value;
        }
        return getCRC(para);
    }

    /**
     * 计算CRC16校验码
     *
     * @param bytes 字节数组
     * @return {@link String} 校验码
     * @since 1.0
     */
    public static String getCRC(byte[] bytes) {
        int wCRCin = 0x0000; // initial value 65535
        int wCPoly = 0x1021; // 0001 0000 0010 0001 (0, 5, 12)
        for (byte b : bytes) {
            for (int i = 0; i < 8; i++) {
                boolean bit = ((b >> (7 - i) & 1) == 1);
                boolean c15 = ((wCRCin >> 15 & 1) == 1);
                wCRCin <<= 1;
                if (c15 ^ bit)
                    wCRCin ^= wCPoly;
            }
        }
        wCRCin &= 0xffff;

        // 结果转换为16进制
        String result = Integer.toHexString(wCRCin).toUpperCase();
        if (result.length() != 4) {
            StringBuffer sb = new StringBuffer("0000");
            result = sb.replace(4 - result.length(), 4, result).toString();
        }
        //高位在前地位在后
//        return result.substring(2, 4) + " " + result.substring(0, 2);
        // 交换高低位，低位在前高位在后
        //return result.substring(2, 4) + " " + result.substring(0, 2);
//        return result.substring(0, 2) + " " + result.substring(2, 4) ;
        return result;
    }




    private static int getUnsignedShort(short data) {

        return data & 0x0FFFF;
    }

    public static byte hexToByte(String inHex)
    {
        return (byte)Integer.parseInt(inHex,16);
    }
    public static int isOdd(int num)
    {
        return num & 0x1;
    }


    /**
     *
     *
     * @param byte_1 Sou1原数组1
     * @param byte_2 Sou2原数组2
     * @return bytestr 返回一个新的数组，包括了原数组1和原数组2
     */
    public static byte[] subPackage(byte[] byte_1, byte[] byte_2) {
        // java 合并两个byte数组

        if (byte_1 == null && byte_2 == null) {
            return null;
        } {
            byte[] byte_3 = new byte[byte_1.length + byte_2.length];
            System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
            System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
            return byte_3;
        }

    }

}
